package com.br.semperparata.components.gui;

import java.awt.Component;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.event.ActionListener;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;

import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.ListCellRenderer;

public class ComboBox<E> extends JPanel {
	private static final long serialVersionUID = 1L;
	
	private FlowLayout flowLayout = new FlowLayout(FlowLayout.LEADING, 5, 5);
	
	private JComboBox<E> combo = null;
	private JLabel label = null;
	
	private String methodName = "";
	
	private ListCellRenderer<E> cellRenderer;
	
	public ComboBox() {
		this(null, null);
	}
	
	public ComboBox(String label) {
		this(label, null);
	}
	
	public ComboBox(List<E> items) {
		this(null, items);
	}
	
	public ComboBox(String label, List<E> items) {
		super();
		this.setLayout(flowLayout);
		
		if (label != null) {
			this.label = new JLabel(label);
			this.add(this.label);
		}
		
		combo = new JComboBox<E>();
		
		if (items != null) {
			this.addItems(items);
		}
		
		combo.setRenderer(getCellRenderer());
		
		this.add(this.combo);
	}
	
	public ComboBox<E> addItems(List<E> items) {
		for (E item : items) {
			this.combo.addItem(item);
		}
		return this;
	}
	
	public void setLabelFont(Font font) {
		if (this.label != null)
			this.label.setFont(font);
	}
	
	public void setComboFont(Font font) {
		this.combo.setFont(font);
	}
	
	public void setFonts(Font font) {
		setLabelFont(font);
		setComboFont(font);
	}
	
	public void setItemLabelMethodName(String methodName) {
		this.methodName = methodName;
	}
	
	@SuppressWarnings("rawtypes")
	private ListCellRenderer<E> getCellRenderer() {
		if (cellRenderer == null) {
			final ListCellRenderer renderer = combo.getRenderer();
			cellRenderer = new ListCellRenderer<E>() {
				
				@Override
				@SuppressWarnings("unchecked")
				public Component getListCellRendererComponent(
						JList<? extends E> list, E value, int index,
						boolean isSelected, boolean cellHasFocus) {
					Object v = value;
					if (!methodName.equals("")) {
						try {
							Method method = value.getClass().getMethod(methodName);
							v = method.invoke(value);
						} catch (NoSuchMethodException e) {
							e.printStackTrace();
						} catch (SecurityException e) {
							e.printStackTrace();
						} catch (IllegalAccessException e) {
							e.printStackTrace();
						} catch (IllegalArgumentException e) {
							e.printStackTrace();
						} catch (InvocationTargetException e) {
							e.printStackTrace();
						}
					}
					return renderer.getListCellRendererComponent(list, v, index, isSelected, cellHasFocus);
				}
			};
		}
		return cellRenderer;
	}
	
	public void addActionListener(ActionListener actionListener) {
		this.combo.addActionListener(actionListener);
	}
	
	public void setHgap(int gap) {
		flowLayout.setHgap(5 + gap);
		this.repaint();
	}
}
